package com.cskaoyan.javase.object._2tostring;

/**
 * Object类当中toString()方法的声明为：
 * public String toString()
 * 没有什么特别需要注意的地方，记住它有返回值，并且返回字符串String就可以了。
 *
 * 方法的作用:
 *      1.返回该对象（调用toString方法的对象）的字符串表示。
 *      2.通常，toString()方法会返回一个"以文本方式表示"此对象的字符串。
 *      3.结果应是一个简明但易于读懂的信息表达式。
 *      4.建议所有子类都重写此方法。
 *
 * Object类当中的toString()方法默认实现如下:
 * "return getClass().getName() + "@" + Integer.toHexString(hashCode());"
 * "this.getClass"获取这个对象的运行时类对象,Class对象
 * "getClass().getName()"是获取该类型的全限定类名
 * "this.hashCode()"是Object当中的一个成员方法,该方法的默认实现是通过计算对象的地址,获取一个十进制整数
 *      该方法的返回值,默认实现的情况下,可以认为是对象的十进制地址值
 * "Integer.toHexString()"该方法是将一个十进制的整数转换成十六进制的字符串
 * 于是上述内容,全部合起来就是:
 * "全限定类名 + @ + 对象的十六进制地址值"
 * 上述输出内容,在我们直接输出引用或者用引用参与字符串拼接时,结果是一样
 * 所以:
 *      在Java中,如果直接输出某个引用,或者使用某个引用参与字符串拼接
 *      那么就会隐式的调用该类型的toString方法
 *      输出或者拼接的结果就是toString方法的返回值
 *
 * 那么为什么建议所有子类都重写这个方法呢?
 * 因为如果不重写,默认就是打印对象的地址值,在绝大多数情况,地址值意义不大
 * 我们输出一个对象/引用,更希望的是看到对象中属性的取值
 * 所以toString方法一般都会以"拼接属性取值"的方式重写
 *
 * toString方法的重写:
 * toString方法一般都会以"拼接属性取值"的方式重写
 * 当然一般来说,也不需要手写它的重写,直接alt + insert自动生成即可.
 *
 * 细节问题:
 *      1.toString()方法可以快速自动生成，使用IDEA快捷键Alt + Insert完成。
 *          如果不是特别有需求,特别有必要,不要去手写实现,也不要去修改自动生成的代码
 *      2.toString()方法，普遍来说就是为了完成打印成员变量取值的
 *          不要在里面写一些奇怪的代码。
 *          比如，业务代码，赋值代码等等。
 *          debug模式下,代码走过创建对象,使用对象调用方法等语句时
 *          会自动调用该类下的toString方法来打印对象信息
 *          所以如果在toString()方法中乱写,会带来不良后果.
 *
 *      3.如果类中有引用数据类型成员变量
 *          那就继续拼接它的toString方法结果
 *          当然可以直接"+ 引用"就行了
 *
 *      4.引用输出或者拼接字符串时的toString方法是隐式调用的,那么有没有必要写出来呢?
 *      不要画蛇添足,不要写出来
 *      因为显式直接调用方法有空指针异常的风险
 *      而隐式调用不写出来,没有这个风险
 *
 *
 *
 * @since 10:53
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        /*Student s = new Student(18, 750);
        System.out.println(s);
        System.out.println(s + " ~ hello world!");
        System.out.println(s.score);*/

        /*Student s = new Student(18, 666, new Star("ikun"));
        System.out.println(s);*/

        Student s = new Student(18, 600, null);
        System.out.println(s);


    }
}

class Student {
    int age;
    double score;
    Star s;

    public Student(int age, double score) {
        this.age = age;
        this.score = score;
    }

    public Student(int age, double score, Star s) {
        this.age = age;
        this.score = score;
        this.s = s;
    }

    /*@Override
    public String toString() {
        return "Student{" + " age = " + age + ", score = " + score + " }";
    }*/

    // "+"拼接
    /*@Override
    public String toString() {
        // score = 1000;
        return "Student{" +
                "age=" + age +
                ", score=" + score +
                '}';
    }*/

    // 实际开发中,更推荐使用以下方式
    /*@Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("Student{");
        sb.append("age=").append(age);
        sb.append(", score=").append(score);
        sb.append('}');
        return sb.toString();
    }*/

    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                ", score=" + score +
                ", s=" + s +
                '}';
    }
}

class Star {
    String name;

    public Star(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Star{" +
                "name='" + name + '\'' +
                '}';
    }
}